import React, { useEffect, useMemo, useState } from 'react';
import cls from './index.module.less';
import { XAssignTask } from '@/ts/base/schema';
import { TaskContentType } from '@/ts/base/model';
import {
  getColorName,
  statusMap,
  taskAllStatus,
  taskStatus,
  TaskTreeSummary,
} from '@/ts/core/work/assign/assignTask/status';
import ReportTree from '@/executor/design/reportTreeModal/ReportTree';
import { Resizable } from 'devextreme-react';
import { Form, Input, message, Select } from 'antd';
import OrgIcons from '@/components/Common/GlobalComps/orgIcons';
import SchemaForm from '@/components/SchemaForm';
import { model, kernel } from '@/ts/base';
import { ProFormColumnsType } from '@ant-design/pro-components';
import { IAssignTaskTree } from '@/ts/core/work/assignTree';
import { IAssignTask } from '@/ts/core/work/assign';
import { EntityInput as _EntityInput } from '@/components/Common/EntityInput';
import { IFile, IWork } from '@/ts/core';
import orgCtrl from '@/ts/controller';
import { AssignStatusType, AssignType, NodeType } from '@/ts/base/enum';
import { DatePicker } from '@/components/Common/StringDatePickers/DatePicker';
import { deepClone } from '@/ts/base/common';
import { Workbook } from 'exceljs';
import _ from 'lodash';

const EntityInput: any = _EntityInput;

interface SummaryReceptionStatusInfo {
  status: taskAllStatus;
  label: string;
  color: string;
}

export function AssignTree(props: {
  assignTask: IAssignTask;
  assignTree: IAssignTaskTree | undefined;
  tree: XAssignTask[];
  onNodeSelect: (node: XAssignTask) => void;
  summary?: TaskTreeSummary;
  width?: number;
  readOnly?: boolean;
  exportData?: XAssignTask[];
}) {
  const [leftWidth, setLeftWidth] = useState(props.width ?? 430);
  const [nodeId, setNodeId] = useState('');
  const [searchText, setSearchText] = useState('');
  const [currentTag, setCurrentTag] = useState('total');
  const [open, setOpen] = useState(false);
  const [directory, setDirectory] = useState(props.assignTask.directory);
  const [value, setValue] = useState<model.ReportContent>(
    props.assignTask.distContent! as model.ReportContent,
  );
  const [assignFields, setAssignFields] = useState<any>();
  const [treeData, setTreeData] = useState<XAssignTask[]>(props.tree);
  const [newForm] = Form.useForm();
  const companys = orgCtrl.user.companys;
  const company = useMemo(
    () => companys.find((item) => item.belongId === props.assignTask.belongId),
    [companys, props.assignTask.belongId],
  );
  const groupsProps = useMemo(
    () => company?.targets.filter((group) => group.typeName === '组织群'),
    [company],
  );

  useEffect(() => {
    const { assignTask } = props;
    const { assignContent, taskStatus, metadata, distContent } = assignTask;

    const isTaskValid =
      assignContent &&
      taskStatus !== AssignStatusType.EMPTY &&
      taskStatus !== AssignStatusType.FINISHED;
    if (isTaskValid) {
      const assignType =
        metadata.assignType === AssignType.STEP && metadata.nodeType === NodeType.Summary
          ? AssignType.STEP
          : AssignType.ALL;
      if (assignType === 'all') {
        setAssignFields({
          typeName: '任务',
          assignType,
          periodType: metadata.periodType,
          period: metadata.period,
          assignContent: deepClone(assignContent),
          distContent: deepClone(assignContent),
          taskStatus: AssignStatusType.EMPTY,
          assignName: metadata.assignName,
        });
      } else {
        setAssignFields({
          typeName: '任务',
          assignType,
          periodType: metadata.periodType,
          period: metadata.period,
          assignContent: deepClone(distContent),
          distContent: deepClone(distContent),
          taskStatus: AssignStatusType.EMPTY,
          assignName: metadata.assignName,
        });
      }
    }
  }, [props.assignTask]);

  function selectNode(e: XAssignTask) {
    setNodeId(e.id);
    props.onNodeSelect(e);
  }
  useEffect(() => {
    setTreeData(props.tree);
  }, [props.tree]);
  function renderNode(node: XAssignTask) {
    const taskStatus = (node.taskStatus ?? 'empty') as taskStatus;
    let color = getColorName(statusMap[taskStatus]?.color);
    return (
      <>
        <span style={{ color }}>{node.name}</span>
      </>
    );
  }

  async function updateValue(v: model.ReportContent) {
    let vClone = Object.assign(value, v);
    setValue(vClone);
  }

  const workValidate = async (file: IFile[]): Promise<boolean> => {
    let work = file[0] as IWork;
    await work.loadNode();
    let flag = work.primaryForms.some((value) => {
      return value.typeName === '报表' || '表格';
    });
    if (!flag) {
      message.warning('办事主表中未存在报表类型数据');
    }
    return true;
  };

  const taskModal = () => {
    const columns: ProFormColumnsType<model.ReportContent>[] = [
      {
        title: '任务详情',
        dataIndex: 'content',
        colProps: { span: 24 },
        renderFormItem: () => {
          if (!props.assignTask || !props.assignTask.distContent) {
            return <></>;
          }

          switch (props.assignTask.distContent?.type) {
            case TaskContentType.Report:
              return (
                <div className="report-content-form" style={{ padding: '16px' }}>
                  <Form
                    initialValues={value}
                    form={newForm}
                    layout="vertical"
                    onValuesChange={(_, v) => {
                      updateValue(v);
                    }}>
                    <Form.Item name="applicationId" label="应用" required={true}>
                      <EntityInput
                        readonly={false}
                        typeName="应用"
                        directory={props.assignTask.assignGroup?.directory}
                        rootKey={'disk'}
                        onValueChange={(file: any) => {
                          if (file) {
                            setDirectory(file);
                          }
                        }}
                      />
                    </Form.Item>
                    <Form.Item name="workId" label="办事" required={true}>
                      <EntityInput
                        readonly={false}
                        typeName="办事"
                        directory={directory}
                        validate={workValidate}
                      />
                    </Form.Item>
                    <Form.Item name="sessionId" label="集群" required={true}>
                      <Select placeholder="请选择集群">
                        {groupsProps?.map((option: any, index: number) => (
                          <Select.Option key={index} value={option.id}>
                            {option.name}
                          </Select.Option>
                        ))}
                      </Select>
                    </Form.Item>
                    <Form.Item name="startDate" label="填报开始时间">
                      <DatePicker picker="date" format="YYYY-MM-DD 00:00:00" />
                    </Form.Item>
                    <Form.Item name="endDate" label="填报结束时间">
                      <DatePicker picker="date" format="YYYY-MM-DD 23:59:59" />
                    </Form.Item>
                  </Form>
                </div>
              );
            default:
              return <></>;
          }
        },
      },
    ];
    return (
      <SchemaForm<model.ReportContent>
        open={open}
        title={'任务分发'}
        width={640}
        columns={columns}
        initialValues={{}}
        rowProps={{
          gutter: [24, 0],
        }}
        layoutType="ModalForm"
        onOpenChange={(open: boolean) => {
          if (!open) {
            setOpen(open);
          }
        }}
        onFinish={async () => {
          let values = Object.assign({}, {}, value);
          values.typeName = '任务模板';
          await props.assignTask.distAssignTask(values);
          setOpen(false);
        }}
      />
    );
  };

  const renderTag = (info: SummaryReceptionStatusInfo, child = false) => {
    const sum = props.summary!;
    let tagValue = sum[info.status as taskStatus] || 0;

    const e = () => {
      return (
        <div
          key={info.status}
          className={[cls['tag'], child ? cls['is-small'] : ''].join(' ')}
          style={{
            color: info.status === currentTag ? '#FFFFFF' : getColorName(info.color),
            backgroundColor: info.status === currentTag ? '#154ad8' : '#F0F0F0',
          }}
          onClick={() => setCurrentTag(info.status)}>
          <div style={{ fontSize: '11px' }}>{info.label}</div> <strong>{tagValue}</strong>
        </div>
      );
    };
    // if (info.status == 'approving' && !child) {
    //   tagValue = sum.submitted + sum.changed;
    //   return (
    //     <div className={cls['tag-wrap']}>
    //       {e()}
    //       {renderTag(statusMap.submitted, true)}
    //       {renderTag(statusMap.changed, true)}
    //     </div>
    //   );
    // } else if (info.status == 'approved' && !child) {
    //   tagValue = sum.finished + sum.rejected;
    //   return (
    //     <div className={cls['tag-wrap']}>
    //       {e()}
    //       {renderTag(statusMap.finished, true)}
    //       {renderTag(statusMap.rejected, true)}
    //     </div>
    //   );
    // } else {
    return e();
    // }
  };

  const exportTreeStructure = async (exportData, assignTask) => {
    if (!exportData || exportData.length <= 0) {
      message.warning('当前任务无树形');
      return;
    }

    let isMessageShown = false;
    try {
      const workbook = new Workbook();
      const sheet = workbook.addWorksheet('当前树形结构');
      sheet.addRow([
        '节点编码',
        '上级节点编码',
        '节点名称',
        '节点类型',
        '归属组织信用代码',
      ]);
      const stack = exportData.map((node) => ({ node, parentId: null, level: 0 }));
      const rows = [];
      // 分批处理节点，每批处理 50 个
      const batchSize = 50;
      while (stack.length > 0) {
        const batch = stack.splice(0, batchSize);
        const belongIds = batch.map(({ node }) => node.belongId);
        // 批量查询目标对象
        const targetsResponse = await kernel.queryTargetById({
          ids: belongIds,
        });
        if (targetsResponse.success && targetsResponse.data) {
          const targetsMap = new Map(
            targetsResponse.data.result.map((target) => [target.id, target.code]),
          );
          for (const { node, parentId, level } of batch) {
            const indent = level > 0 ? _.repeat('　', level) : '';
            const code = targetsMap.get(node.belongId) || '';
            let row = [node.id, parentId, indent + node.name, node.nodeTypeName, code];
            rows.push(row);

            for (const child of node.children.reverse()) {
              stack.push({ node: child, parentId: node.id, level: level + 1 });
            }
          }
        }
        if (!isMessageShown) {
          message.loading('正在处理节点数据,请稍后', 0);
          isMessageShown = true;
        }
      }
      sheet.addRows(rows);
      // 异步生成并下载文件
      const buffer = await workbook.xlsx.writeBuffer();
      const fileName = `${assignTask.name}树形结构.xlsx`;
      const file = new File([buffer], fileName, { type: 'application/octet-stream' });
      const url = URL.createObjectURL(file);
      const link = document.createElement('a');
      link.href = url;
      link.download = fileName;
      link.click();
      URL.revokeObjectURL(url);
      message.destroy();
    } catch (error) {
      message.error(error instanceof Error ? error.message : String(error));
    }
  };

  return (
    <>
      <Resizable
        handles={'right'}
        width={leftWidth}
        maxWidth={640}
        minWidth={280}
        onResize={(e) => setLeftWidth(e.width)}>
        <div className={cls['tree-wrap']}>
          <div className={cls['search-box']}>
            <Input.Search
              placeholder="搜索节点"
              allowClear
              onSearch={(e) => setSearchText(e)}
            />
            {props.assignTask.metadata.nodeType === NodeType.Summary &&
              props.assignTask.metadata.taskStatus === 'received' &&
              (props.assignTask.metadata.assignType === 'step' ||
                props.assignTask.metadata.modelId) && (
                <div className="chat-leftBar-search_more" style={{ marginLeft: '5px' }}>
                  <OrgIcons
                    type="/operate/distribute"
                    size={22}
                    notAvatar
                    title="分发界面"
                    onClick={() => {
                      setOpen(true);
                    }}
                  />
                </div>
              )}
            <div className="chat-leftBar-search_more" style={{ marginLeft: '5px' }}>
              <OrgIcons
                type="/operate/shortcut"
                size={22}
                notAvatar
                title="导出上报状态"
                onClick={async () => {
                  if (!props.exportData || props.exportData.length <= 0) {
                    message.warning('当前任务无树形');
                    return;
                  }
                  try {
                    const workbook = new Workbook();
                    const sheet = workbook.addWorksheet('上报状态');
                    sheet.addRow(['节点名称', '节点类型', '上报状态']);
                    const stack = props.exportData.map((node) => ({ node, level: 0 }));
                    const rows = [];
                    while (stack.length > 0) {
                      const { node, level } = stack.pop()!;
                      const indent = level > 0 ? _.repeat('　', level) : '';
                      let row = [indent + node.name, node.nodeTypeName, '未接收'];
                      row[2] = statusMap[node.taskStatus].label;
                      rows.push(row);
                      for (const child of node.children.reverse()) {
                        stack.push({ node: child, level: level + 1 });
                      }
                    }
                    sheet.addRows(rows);
                    const buffer = await workbook.xlsx.writeBuffer();
                    const fileName = `${props.assignTask.name}上报状态.xlsx`;
                    const file = new File([buffer], fileName, {
                      type: 'application/octet-stream',
                    });
                    const url = URL.createObjectURL(file);
                    const link = document.createElement('a');
                    link.href = url;
                    link.download = fileName;
                    link.click();
                    URL.revokeObjectURL(url);
                  } catch (error) {
                    message.error(error instanceof Error ? error.message : String(error));
                  }
                }}
              />
            </div>
            <div className="chat-leftBar-search_more" style={{ marginLeft: '5px' }}>
              <OrgIcons
                type="/operate/shortcut"
                size={22}
                notAvatar
                title="导出当前树形结构"
                onClick={async () => {
                  exportTreeStructure(props.exportData, props.assignTask);
                }}
              />
            </div>
          </div>
          {props.assignTask.metadata.nodeType === NodeType.Summary && (
            <>
              <div
                className={cls['info'] + ' ' + cls['tree-tags']}
                style={{ marginBottom: '8px' }}>
                {renderTag({
                  status: 'total',
                  label: '全部',
                  color: '',
                })}
                {renderTag(statusMap.empty)}
                {renderTag(statusMap.received)}
                {renderTag(statusMap.submitted)}
                {renderTag(statusMap.finished)}
              </div>
            </>
          )}
          <div className={cls['tree-content']}>
            <ReportTree<any>
              nodes={props.tree}
              current={props.assignTree}
              type={'assign'}
              selectedKeys={nodeId ? [nodeId] : []}
              renderNode={renderNode}
              onSelect={(_, n) => {
                selectNode(n.node);
              }}
              checkable={true}
              currentTag={currentTag}
              searchText={searchText}
              externalField={assignFields}
              curRootNodeId={props.assignTask.id}
            />
          </div>
        </div>
      </Resizable>
      {taskModal()}
    </>
  );
}
